#include <cv.h>
#include <highgui.h>
#include <glew.h>
#include <glut.h>
#include <stdio.h>
#include <Cg/cgGL.h>
#include <time.h>

#pragma comment( lib,"glew32.lib" )
#pragma comment( lib,"cv.lib" )
#pragma comment( lib,"highgui.lib" )
#pragma comment( lib,"cxcore.lib" )
#pragma comment( lib,"cg.lib" )
#pragma comment( lib,"cgGL.lib" )


GLuint fbo;					// Our handle to the FBO
GLuint img,texInput,InfoID;					// Our handle to a texture


float  * data;
IplImage *pImage;
int istep,iwidth,iheight;
float* tex;


CGcontext cgContext;
CGprofile fragmentProfile;
CGprogram fragmentProgram;
CGparameter cgData,cgInfo;
FILE *f;
int imgw,imgh,imgx,imgy;
float* info;
clock_t start, end;

void init(GLvoid)     
{
	f=fopen("exchangedata0.txt","r");

	if (f==NULL)
	{
		printf("error");
		return;
	}


	float a,b;

	fscanf(f,"%d,%d,%d,%d\n",&imgx,&imgy,&imgw,&imgh);

	int n=imgw*imgh;

	info=new float[n*3]();

	int ta,tb,index;

	for (int i=0;i<n;i++)
	{
		info[i*3]=-1;
		info[i*3+1]=0;
		info[i*3+2]=0;
	}


	for (int i=0;i<imgh;i++)
	{
		for (int j=0;j<imgw;j++)
		{
			fscanf(f,"%d,%f,%f\n",&index,&a,&b);

			ta=(int)a;
			tb=(int)b;

			info[index*3]=index;
			info[index*3+1]=ta;
			info[index*3+2]=tb;

		}

	}





	pImage=cvLoadImage("tifa1.jpg",CV_LOAD_IMAGE_COLOR);

	istep=pImage->widthStep;
	iheight=pImage->height;
	iwidth=pImage->width;
	unsigned char *sdata=(unsigned char*)pImage->imageData;
	tex=new float[iwidth*iheight*3];


	for (int i=0; i<iheight*iwidth*3; i++) {
		tex[i] = sdata[i];
	}

	data=new float [imgw*imgh*3];
	glClearColor(0.0f, 0.0f, 0.2f, 0.5f);
	glViewport(0,0,imgw,imgh);



	glGenTextures(1, &texInput);
	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texInput);
	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB,  iwidth, iheight, 0, GL_RGB, GL_FLOAT, 0);

	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);


	glGenTextures(1, &InfoID);
	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, InfoID);
	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB,  imgw, imgh, 0, GL_RGB, GL_FLOAT, 0);

	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);

	glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,imgw,imgh,GL_RGB,GL_FLOAT,info);


	glGenFramebuffersEXT(1, &fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	glGenTextures(1, &img);
	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, img);
	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB,  imgw, imgh, 0, GL_RGB, GL_FLOAT, 0);
	

	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, img, 0);



	

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);	




	cgContext = cgCreateContext();
	fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
	cgGLSetOptimalOptions(fragmentProfile);
	fragmentProgram = cgCreateProgramFromFile (cgContext, CG_SOURCE, "GP.cg", fragmentProfile, 0, 0);
	cgGLLoadProgram (fragmentProgram);


	cgData = cgGetNamedParameter (fragmentProgram, "textureY");
	cgInfo = cgGetNamedParameter(fragmentProgram,"textureInfo");
}

void ShutDown(GLvoid)
{
	glDeleteFramebuffersEXT(1, &fbo);
	glDeleteTextures(1,&img);
}

void reshape(int w,int h)			
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, imgw, 0.0, imgh);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glViewport(0, 0, imgw, imgh);			
}


void idle(void)
{
	glutPostRedisplay();
}

void display(void)   
{

	start=clock();
	
	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texInput);


	glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,iwidth,iheight,GL_RGB,GL_FLOAT,tex);

	cgGLEnableProfile(fragmentProfile);
	cgGLBindProgram(fragmentProgram);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	//glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);

	glClearColor(1.0,0.0,0.0,1.0);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	

	cgGLSetTextureParameter(cgData, texInput);
	cgGLEnableTextureParameter(cgData);

	cgGLSetTextureParameter(cgInfo, InfoID);
	cgGLEnableTextureParameter(cgInfo);

	glPolygonMode(GL_FRONT,GL_FILL);

	

	glBegin(GL_QUADS);
	// Front Face
	glTexCoord2f(0, 0);
	glVertex2f(0, 0);
	glTexCoord2f(imgw, 0);
	glVertex2f(imgw,0);
	glTexCoord2f(imgw, imgh);
	glVertex2f(imgw,imgh);
	glTexCoord2f(0, imgh);
	glVertex2f(0,imgh);
	
	glEnd();

	//glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
	glReadPixels(0, 0, imgw, imgh,GL_RGB,GL_FLOAT,data);

	
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	
	cgGLDisableProfile(fragmentProfile);

	glDrawPixels(imgw,imgh,GL_RGB,GL_FLOAT,data);

	

	
	glutSwapBuffers ( );

	end=clock();
	printf("%d\n",end-start);

	
}

int main(int argc, char** argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE );		// Display Mode
	glutInitWindowSize(621,437);
	glutCreateWindow( "Fuck" );
	glewInit();

	

	init();

	// Setup the various call back functions GLUT requires
	glutDisplayFunc     ( display );  
	glutReshapeFunc     ( reshape );
	glutIdleFunc		( idle );
	glutMainLoop        ( );			// Run the main GLUT loop for rendering

	return 0;
}

